#include "Constantes_Globals.h"

void imprimeProcesso(Processo processo)
{
    int i;
    
    fprintf(log_file,"----------DADOS DO PROCESSO---------\n");
    fprintf(log_file,"   Id do processo:        %d\n", processo.pid);
    fprintf(log_file,"   Prioridade:            %d\n",processo.prioridade);        
    fprintf(log_file,"   Instrucoes:            %d\n",processo.instrucoes);
    fprintf(log_file,"   Entrada e Saida:       %d\n",processo.entradasaida);        
    fprintf(log_file,"   Regiao Critica:        %d\n",processo.regiaocritica);    
    fprintf(log_file,"   Erro Fatal:            %d\n", processo.errofatal);
    fprintf(log_file,"   Referencia de Memoria: %d\n\n",processo.referenciamemoria);            
    fprintf(log_file,"   Instruções mais importantes: %d\n\t\t",processo.tam_instrucoes_importantes);        
    
    for(i=0; i<processo.tam_instrucoes_importantes; i++)
        fprintf(log_file,"%d ",processo.instrucoes_importantes[i]);
    
    fprintf(log_file,"\n\n");
    fprintf(log_file,"   Instruções menos importantes: %d\n\t\t",processo.tam_instrucoes_menos_importantes);
    
    for(i=0; i<processo.tam_instrucoes_menos_importantes; i++)
        fprintf(log_file,"%d ",processo.instrucoes_menos_importantes[i]);    
    
    fprintf(log_file,"\n\n");
    fprintf(log_file,"   Recursos a requisitar: ");
    
    for(i=0; i<TAM_MAX_REQUISTO_RECURSO; i++)
        fprintf(log_file,"%d ",processo.recursos_necessarios[i]);
    
    fprintf(log_file,"\n\n");
}

FILE* abreArquivoLeitura(char* nome_arquivo){
    FILE* file = fopen(nome_arquivo,"rb");
    if (file == NULL) {
        fprintf(log_file,"Houve um erro ao abrir o arquivo xx%s.\n",nome_arquivo);
        return;
    }    
    return file;
}

FILE* abreArquivoEscrita(char* nome_arquivo){
    FILE* file = fopen(nome_arquivo,"wb");
    if (file == NULL) {
        fprintf(log_file,"Houve um erro ao abrir o arquivo.\n");
        return;
    }    
    return file;
}

void fechaArquivo(FILE* file){
    fclose(file);
}

void gravaProcesso(Processo* p, char* file ){
    FILE* fp = abreArquivoEscrita(file);
    fwrite(p, sizeof(Processo), 1, fp);    
    fechaArquivo(fp);
}

void instanciaProcesso(FILE* file, Processo* p){    
    fread(p, sizeof(Processo), 1, file);        
    fechaArquivo(file);
}


void setProcesso(Processo* p, int pid, int prioridade, int instrucoes, int entradasaida, 
                int regiaocritica, int errofatal, int referenciamemoria, int chamadasistema, 
                int tam_instrucoes_importantes, int instrucoes_importantes[], int tam_instrucoes_menos_importantes,
                int instrucoes_menos_importantes[], int recursos_necessarios[])
{
    p->pid = pid;
    p->prioridade = prioridade;           
    p->instrucoes = instrucoes;
    p->entradasaida = entradasaida;
    p->regiaocritica = regiaocritica;
    p->errofatal = errofatal;
    p->referenciamemoria = referenciamemoria;
    p->chamadasistema = chamadasistema;    
    p->tam_instrucoes_importantes = tam_instrucoes_importantes;       
    p->recursos_indicador = 0;
    
    int i;
    
    for(i=0; i<tam_instrucoes_importantes; i++)
        p->instrucoes_importantes[i] = instrucoes_importantes[i];            
    
    p->tam_instrucoes_menos_importantes = tam_instrucoes_menos_importantes;
    
    for(i=0; i<tam_instrucoes_menos_importantes; i++)
        p->instrucoes_menos_importantes[i]=instrucoes_menos_importantes[i];
    
    for(i = 0; i<TAM_MAX_REQUISTO_RECURSO; i++)
        p->recursos_necessarios[i] = recursos_necessarios[i];
    
    for (i = 0; i < TAM_MAX_REQUISTO_RECURSO; i++)
    {
        p->recursos_alocados[i].id = -1;   
        p->recursos_alocados[i].contador = rand()%505;      
    }
}

void setTabelaProcesso(Processo*p, TabelaProcesso *tb)
{
    p->tabelaProcesso = tb;
}

void criaProcesso(char* nome_arquivo, Processo* processo)
{
    FILE* fp = abreArquivoLeitura(nome_arquivo);        
    instanciaProcesso(fp,processo);
    
    int i;
    
    printf("\nProcesso %d\n", processo->pid);
    
    for(i=0; i<TAM_MAX_REQUISTO_RECURSO; i++)
    {
        printf("%d (%d),  ", processo->recursos_alocados[i].id, processo->recursos_alocados[i].contador);
    }
    
    
    processo->recursos_indicador = 0;
    //após o pessoal do Sistema de arquivo fazer a parte deles tem que alterar o 2º parâmetro
    
    //cria uma nova tabela de processo no vetor
    tabela_processos[posicao_livre_tabela_processos] = tb_nova(processo, 0, QUANTUM, sizeof(fp));   
    //o endereco dessa tabela vai processo    
    setTabelaProcesso(processo,tabela_processos[posicao_livre_tabela_processos]);
    posicao_livre_tabela_processos++;//incrementa posicoes livres do vetor de tabela de processos;
    
    //double inicio = startTime();
    //sleep(2);
    //double fim = pauseTime();
    //printf("\nO processo %d passou %fms na CPU\n\n",processo.pid, currentTime(inicio,fim));        
    MMU(*processo);    
}

/**
 * Tabela de Processos - Sistemas Operacionais
 * --------------------------------------
 *
 * 1. estado do processo:
 *      1- Pronto
 *      2 - Bloqueado
 *      3 - Executando
 * 2. seu contador de programa: posicao do vetor de memoria
 * 3. alocação de memória: peso do arquivo
 * 4. estados de seus arquivos abertos:  Responsabilidade do grupo de arquivos por enquanto vai ser rancomico
 * 5. quantum: tempo definido para execucao
 *
 * @author Caio Thomas Oliveira 11011BSI209
 * @author Matheus Ferreira da Silva 11011BSI234
 * @author Leonardo Pimentel Ferreira	11011BSI223
 */

TabelaProcesso*
tb_nova(Processo* processo, int arquivoAberto, int quantum, int qtdMemoriaAlocada)
{
    TabelaProcesso *tp =  malloc(sizeof(TabelaProcesso));

    tp->id = processo->pid;//id do processo
    tp->quantum = quantum;//quanta será definido pelo escalonamento
    tp->arquivoAberto = arquivoAberto;//quantidade de arquivos abertos
    tp->quantidadeMemoriaAlocada = qtdMemoriaAlocada;//quanto pesa o arquivo
    tp->prioridade = processo->prioridade;// 0 nucleo - 1 usuario
    tp->estado = 0;//inicialmente sera 0 pois verificado em execucao
    tp->contadorPrograma = 0;//inicialmente 0, durante a exeucao o contador de programa aumenta
    return tp;
}

void
tb_imprime(TabelaProcesso* tp)
{
    fprintf(log_file,"----------TABELA DE PROCESSO PID %d---------\n", tp->id);
    fprintf(log_file,"Estado:               %d\n", tp->estado);
    fprintf(log_file,"Prioridade:           %d\n", tp->prioridade);
    fprintf(log_file,"Contador de Programa: %d\n", tp->contadorPrograma);
    fprintf(log_file,"Quantum:              %d\n", tp->quantum);
    fprintf(log_file,"Arquivos Abertos:     %d\n", tp->arquivoAberto);
    fprintf(log_file,"Qtd Memoria Alocada:  %d\n", tp->quantidadeMemoriaAlocada);
}

